/**
 * 性能优化工具
 * 提供防抖、节流、懒加载等性能优化功能
 */

/**
 * 防抖函数
 * @param {Function} func - 要防抖的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function} 防抖后的函数
 */
export const debounce = (func, delay = 300, immediate = false) => {
  let timeoutId = null;
  let lastCallTime = 0;

  return function debounced(...args) {
    const now = Date.now();
    const callNow = immediate && !timeoutId;

    clearTimeout(timeoutId);

    if (callNow) {
      lastCallTime = now;
      return func.apply(this, args);
    }

    timeoutId = setTimeout(() => {
      timeoutId = null;
      if (!immediate) {
        lastCallTime = Date.now();
        func.apply(this, args);
      }
    }, delay);
  };
};

/**
 * 节流函数
 * @param {Function} func - 要节流的函数
 * @param {number} delay - 延迟时间（毫秒）
 * @param {Object} options - 选项
 * @returns {Function} 节流后的函数
 */
export const throttle = (func, delay = 300, options = {}) => {
  let timeoutId = null;
  let lastExecTime = 0;
  const { leading = true, trailing = true } = options;

  return function throttled(...args) {
    const now = Date.now();
    const timeSinceLastExec = now - lastExecTime;

    const execute = () => {
      lastExecTime = now;
      func.apply(this, args);
    };

    if (timeSinceLastExec >= delay) {
      if (leading) {
        execute();
      }
    } else if (trailing && !timeoutId) {
      timeoutId = setTimeout(() => {
        timeoutId = null;
        if (trailing) {
          execute();
        }
      }, delay - timeSinceLastExec);
    }
  };
};

/**
 * 创建一个可取消的Promise
 * @param {Function} executor - Promise执行器
 * @returns {Object} 包含promise和cancel方法的对象
 */
export const createCancelablePromise = (executor) => {
  let isCanceled = false;
  let cancelCallback = null;

  const promise = new Promise((resolve, reject) => {
    const wrappedResolve = (value) => {
      if (!isCanceled) {
        resolve(value);
      }
    };

    const wrappedReject = (reason) => {
      if (!isCanceled) {
        reject(reason);
      }
    };

    executor(wrappedResolve, wrappedReject, (callback) => {
      cancelCallback = callback;
    });
  });

  const cancel = () => {
    isCanceled = true;
    if (cancelCallback) {
      cancelCallback();
    }
  };

  return { promise, cancel };
};

/**
 * 图片懒加载
 * @param {HTMLImageElement} img - 图片元素
 * @param {string} src - 图片源地址
 * @param {Object} options - 选项
 */
export const lazyLoadImage = (img, src, options = {}) => {
  const {
    placeholder = '',
    rootMargin = '50px',
    threshold = 0.1
  } = options;

  // 设置占位符
  img.src = placeholder;

  // 创建Intersection Observer
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const image = entry.target;
          image.src = src;
          
          // 加载完成后移除观察
          image.onload = () => {
            observer.unobserve(image);
          };
          
          // 加载失败处理
          image.onerror = () => {
            observer.unobserve(image);
            console.warn('图片加载失败:', src);
          };
        }
      });
    },
    {
      rootMargin,
      threshold
    }
  );

  observer.observe(img);

  // 返回清理函数
  return () => {
    observer.unobserve(img);
    observer.disconnect();
  };
};

/**
 * 批量处理函数
 * @param {Function} processor - 处理函数
 * @param {number} batchSize - 批次大小
 * @param {number} delay - 批次间延迟
 * @returns {Function} 批量处理函数
 */
export const batchProcessor = (processor, batchSize = 10, delay = 0) => {
  return async (items) => {
    const results = [];
    
    for (let i = 0; i < items.length; i += batchSize) {
      const batch = items.slice(i, i + batchSize);
      const batchResults = await Promise.all(
        batch.map(item => processor(item))
      );
      
      results.push(...batchResults);
      
      // 批次间延迟
      if (delay > 0 && i + batchSize < items.length) {
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
    
    return results;
  };
};

/**
 * 内存缓存类
 */
export class MemoryCache {
  constructor(maxSize = 100, ttl = 5 * 60 * 1000) { // 默认5分钟TTL
    this.cache = new Map();
    this.maxSize = maxSize;
    this.ttl = ttl;
  }

  set(key, value, customTtl) {
    const expireTime = Date.now() + (customTtl || this.ttl);
    
    // 如果缓存已满，删除最旧的项
    if (this.cache.size >= this.maxSize) {
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    
    this.cache.set(key, {
      value,
      expireTime
    });
  }

  get(key) {
    const item = this.cache.get(key);
    
    if (!item) {
      return null;
    }
    
    // 检查是否过期
    if (Date.now() > item.expireTime) {
      this.cache.delete(key);
      return null;
    }
    
    return item.value;
  }

  has(key) {
    return this.get(key) !== null;
  }

  delete(key) {
    return this.cache.delete(key);
  }

  clear() {
    this.cache.clear();
  }

  // 清理过期项
  cleanup() {
    const now = Date.now();
    for (const [key, item] of this.cache.entries()) {
      if (now > item.expireTime) {
        this.cache.delete(key);
      }
    }
  }

  // 获取缓存统计信息
  getStats() {
    return {
      size: this.cache.size,
      maxSize: this.maxSize,
      keys: Array.from(this.cache.keys())
    };
  }
}

/**
 * 创建全局缓存实例
 */
export const globalCache = new MemoryCache();

/**
 * 带缓存的异步函数包装器
 * @param {Function} asyncFunc - 异步函数
 * @param {Object} options - 选项
 * @returns {Function} 带缓存的函数
 */
export const withCache = (asyncFunc, options = {}) => {
  const {
    cache = globalCache,
    keyGenerator = (...args) => JSON.stringify(args),
    ttl
  } = options;

  return async (...args) => {
    const key = keyGenerator(...args);
    
    // 尝试从缓存获取
    const cached = cache.get(key);
    if (cached !== null) {
      return cached;
    }
    
    // 执行函数并缓存结果
    try {
      const result = await asyncFunc(...args);
      cache.set(key, result, ttl);
      return result;
    } catch (error) {
      // 不缓存错误结果
      throw error;
    }
  };
};

/**
 * 请求去重
 * 防止相同的请求同时发起多次
 */
export class RequestDeduplicator {
  constructor() {
    this.pendingRequests = new Map();
  }

  async deduplicate(key, requestFunc) {
    // 如果已有相同请求在进行中，返回该请求的Promise
    if (this.pendingRequests.has(key)) {
      return this.pendingRequests.get(key);
    }

    // 创建新请求
    const promise = requestFunc()
      .finally(() => {
        // 请求完成后清理
        this.pendingRequests.delete(key);
      });

    this.pendingRequests.set(key, promise);
    return promise;
  }

  clear() {
    this.pendingRequests.clear();
  }
}

/**
 * 创建全局请求去重器实例
 */
export const globalDeduplicator = new RequestDeduplicator();